<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue2与Vue3数据响应式原理</title>
</head>

<body>
  <h1>Vue2的数据响应式案例</h1>
  <h3 id="h3">1</h3>
  <button id="btnv2">点击后数字++</button>
  <script>
    var data = { num: 1 }
    btnv2.onclick = function () {
      data.num++
    }
    // 监听data中num的变化，一旦有变化，自动更新h3
    Object.defineProperties(data, {
      _num: { value: 1, writable: true },
      num: { // 监听data的num属性
        get() {
          // 当需要获取data.num值时，将会自动执行该get方法
          return this._num
        },
        set(value) {
          // 当修改data.num时，将自动执行该set方法 并传入目标值
          this._num = value
          // 顺便可以更新UI
          h3.innerHTML = value
        },
      }
    })

  </script>

  <h1>Vue3的数据响应式案例</h1>
  <h3 id="h3v3">1</h3>
  <button id="btnv3">点击后数字++</button>
  <script>
    var datav3 = { num: 1 }
    btnv3.onclick = function () {
      // 错误，不应该使用真实对象
      // datav3.num++

      // 正确，应该操作的是代理对象，代理会修改目标对象的属性，同时更新UI
      proxy.num++
    }

    // 对于vue3，将会对datav3对象创建代理对象，由代理对象来管理数据更新
    // new Proxy()将会创建代理对象   
    // 参数1：datav3 就是代理对象的目标对象
    // 参数2：object 提供代理的细节 get   set
    var proxy = new Proxy(datav3, {
      // 当访问datav3的属性时，将会执行get方法 传入两个参数：
      // obj 当前代理对象的目标对象
      // key 所访问的属性名  例如：datav3.num    key就是 'num'
      get(obj, key) {
        return obj[key]
      },
      // 当修改datav3的属性时，就会执行set方法，传入3个参数：
      // value 就是要做属性设置的目标值
      set(obj, key, value) {
        obj[key] = value  // 将目标对象的属性值做一次真实修改
        h3v3.innerHTML = value
      }
    })


  </script>

</body>

</html>